#include "preHeader.h"
#include "Session/GameSession.h"
#include "Session/GameSessionHandler.h"
#include "SQLHelper.h"

int GameSessionHandler::HandleLoadAllOperatingActivity(GameSession *pSession, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	auto LoadAllOperatingActivity = [GSRPCAsyncTaskArgs]() {
		uint32 actType, actTimes;
		(*pckPtr) >> actType >> actTimes;
		AutoFeedbackLarge(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		size_t n = 0;
		uint32 lastInstID = 0;
		auto sqlFormat = CreateSQL4SelectEntity<OperatingActivityData>(
			"actType=%u AND actTimes=%u AND playerId>%u ORDER BY actType,actTimes,playerId");
mark:	auto rst = connPtr->FastQueryFormat(sqlFormat.c_str(), actType, actTimes, lastInstID);
		if (!rst) {
			error = DBPErrorQueryMysqlFailed;
			return;
		}
		while (rst.NextRow()) {
			auto row = rst.Fetch();
			auto instInfo = LoadEntityFromMysqlRow<OperatingActivityData>(row);
			SaveToINetStream(instInfo, buffer);
			lastInstID = instInfo.playerId;
			if (++n % 1000 == 0) {
				GameSession::Feedback(gsPtr, buffer, info.sn, RPCErrorNone, false);
				buffer.Clear();
			}
		}
		if (connPtr->GetLastErrno() != 0) {
			goto mark;
		}
	};
	sDeferAsyncTaskMgr.AddTask(CreateAsyncTask(LoadAllOperatingActivity));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleSaveOperatingActivity(GameSession *pSession, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	auto SaveOperatingActivity = [GSRPCAsyncTaskArgs]() {
		static const std::vector<ssize_t> ingores =
			ConvertEntityFieldIndexs<OperatingActivityData>({
			"playerId","actType","actTimes"});
		AutoFeedback(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		AutoTransaction_FailReturn(connPtr, error)
		while (!pckPtr->IsReadableEmpty()) {
			OperatingActivityData instInfo;
			LoadFromINetStream(instInfo, *pckPtr);
			auto sqlStr = CreateSQL4InsertOrUpdateEntity(instInfo, ingores);
			auto rst = connPtr->Execute(sqlStr.c_str());
			DBGASSERT(rst.second);
		}
	};
	sDeferAsyncTaskMgr.AddTask(CreateAsyncTask(SaveOperatingActivity), NULL, 0);
	return SessionHandleCapture;
}

int GameSessionHandler::HandleCleanupOperatingActivity(GameSession *pSession, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	auto CleanupOperatingActivity = [GSRPCAsyncTaskArgs]() {
		std::unordered_set<uint64> workingActUniqueKeys;
		while (!pckPtr->IsReadableEmpty()) {
			workingActUniqueKeys.insert(pckPtr->Read<uint64>());
		}
		AutoFeedback(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		auto rst = connPtr->QueryFormat(
			"SELECT actType,actTimes FROM %s GROUP BY actType,actTimes",
			GetTableName<OperatingActivityData>());
		if (!rst) {
			error = DBPErrorQueryMysqlFailed;
			return;
		}
		while (rst.NextRow()) {
			auto row = rst.Fetch();
			auto actType = row.GetUInt32(); row.Next();
			auto actTimes = row.GetUInt32(); row.Next();
			auto actUniqueKey = GetOperatingUniqueKey(actType, actTimes);
			if (workingActUniqueKeys.count(actUniqueKey) != 0) {
				continue;
			}
			auto rstX = connPtr->ExecuteFormat(
				"DELETE FROM %s WHERE actType=%u AND actTimes=%u",
				GetTableName<OperatingActivityData>(), actType, actTimes);
			DBGASSERT(rstX.second);
		}
	};
	sDeferAsyncTaskMgr.AddTask(CreateAsyncTask(CleanupOperatingActivity));
	return SessionHandleCapture;
}
